/*
 * MIT License
 *
 * Copyright (c) 2023 北京凯特伟业科技有限公司
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */
package com.je.bpm.engine.impl.bpmn.behavior;

import com.je.bpm.engine.ActivitiException;
import com.je.bpm.engine.cfg.security.CommandExecutorContext;
import com.je.bpm.engine.cfg.security.CommandExecutorFactory;
import com.je.bpm.engine.delegate.DelegateExecution;
import com.je.bpm.engine.delegate.Expression;
import com.je.bpm.engine.impl.util.CommandExecutor;
import com.je.bpm.engine.impl.util.ShellCommandExecutor;
import com.je.bpm.engine.impl.util.ShellExecutorContext;
import java.util.ArrayList;
import java.util.List;

public class ShellActivityBehavior extends AbstractBpmnActivityBehavior {

    private static final long serialVersionUID = 1L;

    protected Expression command;
    protected Expression wait;
    protected Expression arg1;
    protected Expression arg2;
    protected Expression arg3;
    protected Expression arg4;
    protected Expression arg5;
    protected Expression outputVariable;
    protected Expression errorCodeVariable;
    protected Expression redirectError;
    protected Expression cleanEnv;
    protected Expression directory;

    String commandStr;
    String arg1Str;
    String arg2Str;
    String arg3Str;
    String arg4Str;
    String arg5Str;
    String waitStr;
    String resultVariableStr;
    String errorCodeVariableStr;
    Boolean waitFlag;
    Boolean redirectErrorFlag;
    Boolean cleanEnvBoolean;
    String directoryStr;

    private void readFields(DelegateExecution execution) {
        commandStr = getStringFromField(command, execution);
        arg1Str = getStringFromField(arg1, execution);
        arg2Str = getStringFromField(arg2, execution);
        arg3Str = getStringFromField(arg3, execution);
        arg4Str = getStringFromField(arg4, execution);
        arg5Str = getStringFromField(arg5, execution);
        waitStr = getStringFromField(wait, execution);
        resultVariableStr = getStringFromField(outputVariable, execution);
        errorCodeVariableStr = getStringFromField(errorCodeVariable, execution);

        String redirectErrorStr = getStringFromField(redirectError, execution);
        String cleanEnvStr = getStringFromField(cleanEnv, execution);

        waitFlag = waitStr == null || waitStr.equals("true");
        redirectErrorFlag = "true".equals(redirectErrorStr);
        cleanEnvBoolean = "true".equals(cleanEnvStr);
        directoryStr = getStringFromField(directory, execution);

    }

    @Override
    public void execute(DelegateExecution execution) {

        readFields(execution);

        List<String> argList = new ArrayList<String>();
        argList.add(commandStr);

        if (arg1Str != null) {
            argList.add(arg1Str);
        }
        if (arg2Str != null) {
            argList.add(arg2Str);
        }

        if (arg3Str != null) {
            argList.add(arg3Str);
        }

        if (arg4Str != null) {
            argList.add(arg4Str);
        }

        if (arg5Str != null) {
            argList.add(arg5Str);
        }

        ShellExecutorContext executorContext = new ShellExecutorContext(
                waitFlag,
                cleanEnvBoolean,
                redirectErrorFlag,
                directoryStr,
                resultVariableStr,
                errorCodeVariableStr,
                argList);

        CommandExecutor commandExecutor = null;

        CommandExecutorFactory shellCommandExecutorFactory = CommandExecutorContext.getShellCommandExecutorFactory();

        if (shellCommandExecutorFactory != null) {
            // if there is a ShellExecutorFactoryProvided
            // then it will be used to create a desired shell command executor.
            commandExecutor = shellCommandExecutorFactory.createExecutor(executorContext);
        } else {
            // default Shell executor (if the shell security is OFF)
            commandExecutor = new ShellCommandExecutor(executorContext);
        }

        try {
            commandExecutor.executeCommand(execution);
        } catch (Exception e) {
            throw new ActivitiException("Could not execute shell command ", e);
        }

        leave(execution);
    }

    protected String getStringFromField(Expression expression, DelegateExecution execution) {
        if (expression != null) {
            Object value = expression.getValue(execution);
            if (value != null) {
                return value.toString();
            }
        }
        return null;
    }

}
